package vcp.scheduledtasks;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.TimerTask;


import db.parking.beans.Orders;
import db.parking.beans.Parking;
import db.parking.beans.ParkingLot;
import db.parking.beans.Subscriber;
import db.tables.AdminCheckInOut;
import db.tables.AdminOrders;
import db.tables.AdminParking;
import db.tables.AdminSubscriber;

/**
 * *This class is being ran daily go make daily checks like-
 *1.subscriptions end
 *2.subscription renewal message
 *3.kick subscribers which has finished their subscription and didn't renew it
 * @author Operations
 
 */
public class DailyTimer extends TimerTask {
	ParkingLot[] lot;
	public DailyTimer(ParkingLot[] lot) {
		// TODO Auto-generated constructor stub
		this.lot = lot;
	}

	public void run() {	   
	    Subscriber [] subArray,renewArray;
	    Orders [] fullSubArr;
	    Orders bean = new Orders();
		long time = System.currentTimeMillis();// Set current time at this second to StartTime
		Timestamp currTimestamp = new Timestamp(time);
		Timestamp renewTimestamp = new Timestamp(time);
		Timestamp fullOverload = new Timestamp(time);

		
		
		Calendar cal = Calendar.getInstance();
		cal.setTime(currTimestamp);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(currTimestamp);
		Calendar cal3 = Calendar.getInstance();
		cal3.setTime(currTimestamp);
		
		//check if subscription is over (28 days has passed)
		cal.add(Calendar.DAY_OF_MONTH, -28);
		currTimestamp.setTime(cal.getTime().getTime()); 
		//send a message to user for subscription renewwal(7 days before subscription end)
		cal2.add(Calendar.DAY_OF_MONTH, -21); // add day for the first week
		renewTimestamp.setTime(cal2.getTime().getTime()); // add day for the first week
		//kick full subcriber out of lot after 14 days of parking
		cal3.add(Calendar.DAY_OF_MONTH, -14); // add day for the first week
		fullOverload.setTime(cal3.getTime().getTime()); // add day for the first week
		
		
		
		
	    try {
			subArray = AdminSubscriber.checkSubscriptions(currTimestamp);//get the subscribers that are past 28 days
			
			if(subArray.length > 0)
			{
				for(int i=0;i<subArray.length;i++)
				{
					try {
						AdminSubscriber.delete(subArray[i].getSubID()); //delete from subscriber table
					    bean = AdminOrders.getRow(subArray[i].getCusID(), subArray[i].getCarNo());
						//check if subscriber is parking
						if(bean.getStatus() == 1)
						{
							AdminOrders.updateFinishedSubscriber(subArray[i].getCusID());
							Parking p= new Parking(); 
							p=AdminParking.getRow(subArray[i].getCarNo());
							AdminParking.delete(p.getLotNo(), p.getPositionX(), p.getPositionY(), p.getFloorNo());
							lot[p.getLotNo()-1].setLocation(p.getPositionX(), p.getPositionY(), p.getFloorNo(), 0);
							Orders [] NewestOrders = AdminOrders.getRow(currTimestamp,subArray[i].getLotNo());
							int orderIndex = 0;
							locateParking(NewestOrders, orderIndex,subArray[i].getLotNo());	
							Timestamp now = new Timestamp(time);
						    AdminCheckInOut.insertCheckOut(bean.getOid(), now);
						 }
						
						} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			}
			
			renewArray = AdminSubscriber.checkreNew(renewTimestamp); //send message for renewal 1 week before the end
			
			if(renewArray.length > 0)
			{
				for(int i=0;i<renewArray.length;i++)
				{
					try {
						renewArray[i].setStatus(1);
						AdminSubscriber.update(renewArray[i]);//when status is 1 renewal message has been sent to client
						
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			}
			
			fullSubArr = AdminOrders.getAllFullSubcriber(); //send message for renewal 1 week before the end

			if(fullSubArr.length > 0)
			{
				for(int i=0;i<fullSubArr.length;i++)
				{
					try {
						Timestamp startTime = fullSubArr[i].getStartTime();
						if(fullOverload.getTime() > startTime.getTime())
						{
						    bean = AdminOrders.getRow(fullSubArr[i].getUid(), fullSubArr[i].getCarNo());
							fullSubArr[i].setStatus(2); //kick full subscriber from lot after 14 days		
							AdminOrders.update(fullSubArr[i]);
							Parking p= new Parking(); 
							p=AdminParking.getRow(fullSubArr[i].getCarNo());
			 				AdminParking.delete(p.getLotNo(), p.getPositionX(), p.getPositionY(), p.getFloorNo());
			 				lot[p.getLotNo()-1].setLocation(p.getPositionX(), p.getPositionY(), p.getFloorNo(), 0);
							Orders [] NewestOrders = AdminOrders.getRow(currTimestamp,fullSubArr[i].getLotNo());
							int orderIndex = 0;
							locateParking(NewestOrders, orderIndex,fullSubArr[i].getLotNo());
							Timestamp now = new Timestamp(time);
						    AdminCheckInOut.insertCheckOut(bean.getOid(), now);
						}
											
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			}
			

			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    
	    
	    
	    
	  }
	
	private void locateParking(Orders[] NewestOrders, int orderIndex, int lotId) throws Exception {
		//Reset Lot Before New Entrance
		Parking tmpParking = new Parking();
		int tmpIndex = orderIndex;
		
		if (NewestOrders.length == 0) {		//
			AdminParking.deleteAllLocastions( lotId); //
			for (int z = 0; z < lot[lotId - 1].getZ(); z++)
				for (int y = 0; y < lot[lotId - 1].getY(); y++)
					for (int x = 0; x < lot[lotId - 1].getX(); x++)
						if (lot[lotId - 1].getLocation(x, y, z) == 1)
							lot[lotId - 1].setLocation(x, y, z, 0);
			return;
		}

		
		
		lot[NewestOrders[orderIndex].getLotNo()-1].printLocastions();
		for(int y=0; orderIndex<NewestOrders.length && y < lot[NewestOrders[orderIndex].getLotNo()-1].getY();y++ )
		{
			for (int z=0; orderIndex<NewestOrders.length &&  z < lot[NewestOrders[orderIndex].getLotNo()-1].getZ();z++)
			{
				for(int x=0; orderIndex < NewestOrders.length && x < lot[NewestOrders[orderIndex].getLotNo()-1].getX();x++)
				{
					if(lot[NewestOrders[orderIndex].getLotNo()-1].getLocation(x, y, z) == 1  )
					{
						//Delete row from database so we cant insert a new status
						AdminParking.delete(NewestOrders[orderIndex].getLotNo(),x,y,z);
						//replace updated values in our object
						lot[NewestOrders[orderIndex].getLotNo()-1].setLocation(x, y, z, 0);
						orderIndex++;
					}
				}
			}
		}
		
		//Allocate new parking spot
		for(int y=0; tmpIndex<NewestOrders.length && y < lot[NewestOrders[tmpIndex].getLotNo()-1].getY() ;y++ )
		{
			for (int z=0; tmpIndex<NewestOrders.length && z < lot[NewestOrders[tmpIndex].getLotNo()-1].getZ() ;z++)
			{
				for(int x=0; tmpIndex<NewestOrders.length && x< lot[NewestOrders[tmpIndex].getLotNo()-1].getX() ;x++)
				{
					if(lot[NewestOrders[tmpIndex].getLotNo()-1].getLocation(x, y, z) == 0 
							|| lot[NewestOrders[tmpIndex].getLotNo()-1].getLocation(x, y, z) == 1  )
					{
						lot[NewestOrders[tmpIndex].getLotNo()-1].setLocation(x, y, z, 1);
						//build a new updated bean and update it in database
						tmpParking.setLotNo(NewestOrders[tmpIndex].getLotNo());
						tmpParking.setCarNo(NewestOrders[tmpIndex].getCarNo());
						tmpParking.setFloorNo(z);
						tmpParking.setPositionX(x);
						tmpParking.setPositionY(y);
						tmpParking.setStatus(1);
						AdminParking.insert(tmpParking);
						tmpIndex++;
					}
						
				}	
			}	
		}
	}
}
